package com.hsmpay.qian4.service.ds.impl;

import com.hsmpay.common.pojo.qian4.Qian4SendLog;
import com.hsmpay.common.util.NumberUtil;
import com.hsmpay.mobile.action.account.scanCodePay.MD5;
import com.hsmpay.mobile.action.account.scanCodePay.ScanCodePayParam;
import com.hsmpay.mobile.action.account.scanCodePay.SignUtils;
import com.hsmpay.mobile.action.account.scanCodePay.XmlUtils;
import com.hsmpay.qian4.pojo.PurchaseResult;
import com.hsmpay.qian4.pojo.RevocationResult;
import com.hsmpay.qian4.service.ds.JQScanCodePayService;
import com.hsmpay.utils.DesUtil;
import com.hsmpay.utils.JSONUtil;
import com.hsmpay.utils.WriteFile;
import com.hsmpay.utils.system.ConConfig;
import javapns.org.json.JSONObject;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

@Service("ds_JQScanCodePayService")
public class JQScanCodePayServiceImpl implements JQScanCodePayService{

    public static WriteFile wf = new WriteFile("ds_JQScan");
    private static Logger log = LoggerFactory.getLogger(JQScanCodePayServiceImpl.class);
    private static final String version = "1.0.0";
    public static final String customer_no = "1111111111";
    private static final String MD5Key = "00000000000000000000000000000000";
    private static final String signType = "MD5";
    private static final String openId = ConConfig.getAttribute("WEIXIN_APPID");//微信公众号
    private static final String requestIp = "127.0.0.1";//请求方公网IP
    public static String urlStr = ConConfig.getAttribute("URL_OFFICIAL");

    /**
     * 获取消费二维码
     * @param send
     * @return
     * @throws Exception
     */
    public PurchaseResult getQRCode(Qian4SendLog send, ScanCodePayParam scanCodePayParam, String signatureRelPath) throws Exception {

        String notifyUrl = "http://"+urlStr+"/proOneMobile/JQNotify.action";
        String reqUrl = "http://mu.1spay.com/mu/interface/wxPayOrderNew.action";

        String outTradeNo = scanCodePayParam.getOutTradeNo();
        double totalFee = Double.valueOf(scanCodePayParam.getTotalFee());
        String subOpenId = scanCodePayParam.getSubOpenId();

        log.info("【进钱-收款 请求参数】outTradeNo: "+ outTradeNo);
        log.info("【进钱-收款 请求参数】totalFee: "+ totalFee);
        log.info("【进钱-收款 请求参数】openId: "+ openId);

        wf.log("【进钱-收款 请求参数】outTradeNo: "+outTradeNo, "调试");
        wf.log("【进钱-收款 请求参数】totalFee: "+totalFee, "调试");
        wf.log("【进钱-收款 请求参数】openId: "+openId, "调试");

        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String dateStr = sdf.format(date);
        String reqDate = dateStr.substring(0,8);
        String reqTime = dateStr.substring(8);

        SortedMap<String,String> map = new TreeMap<>();
        map.put("version", version);
        map.put("reqDate", reqDate);
        map.put("transAmount", String.valueOf(NumberUtil.roundF2(totalFee*100).longValue()));//金额转为分
        map.put("bgReturnUrl", notifyUrl);
        map.put("customerNo", customer_no);
        map.put("subOpenId", subOpenId);

        map.put("externalId", outTradeNo);
        map.put("openId", openId);
        map.put("requestIp", requestIp);
        map.put("reqTime", reqTime);
        map.put("description", scanCodePayParam.getBody());
        map.put("selfData",DesUtil.generate32Key());

        Map<String,String> params = SignUtils.paraFilter(map);
        StringBuilder buf = new StringBuilder((params.size() +1) * 10);
        SignUtils.buildPayParams(buf,params,false);
        String preStr = buf.toString();
        String sign = MD5.sign(preStr, "&key=" + MD5Key, "utf-8");
        map.put("sign", sign);

        Map<String,Object> paramMap = new HashMap<>();
        paramMap.putAll(map);
        paramMap.put("transAmount",NumberUtil.roundF2(totalFee*100).longValue());

        JSONObject jsonObject = new JSONObject(paramMap);
        log.info("【进钱-收款 请求参数】:" + jsonObject.toString());

        Map<String, String> resultMap = new HashMap<>();
        if(ConConfig.isFormal()){
            wf.log("【进钱-收款】请求环境:生产环境", "调试");

            CloseableHttpResponse response = null;
            CloseableHttpClient client = null;
            try {
                HttpPost httpPost = new HttpPost(reqUrl);
                StringEntity entityParams = new StringEntity(jsonObject.toString(), "utf-8");
                httpPost.setEntity(entityParams);
                httpPost.setHeader("Content-Type", "text/xml;charset=ISO-8859-1");
                client = HttpClients.createDefault();
                response = client.execute(httpPost);
                if (response != null && response.getEntity() != null) {
                    JSONObject jsonObj = new JSONObject(EntityUtils.toString(response.getEntity()));
                   log.info("【进钱-收款 响应参数】:" + jsonObj.toString());
                   Map<String, String> resultJsonMap = JSONUtil.parseToBean(jsonObj.toString());
                   String payInfoString = resultJsonMap.get("payInfo");
                    if(StringUtils.isNotBlank(payInfoString)){
                        JSONObject payInfo = new JSONObject(payInfoString);
                        Iterator<String> payInfoItr = payInfo.keys();
                        while (payInfoItr.hasNext()) {
                            String name = payInfoItr.next();
                            resultMap.put(name, payInfo.getString(name));
                        }
                        jsonObj.remove("payInfo");
                    }
                    Iterator<String> nameItr = jsonObj.keys();
                    while (nameItr.hasNext()) {
                        String name = nameItr.next();
                        resultMap.put(name, jsonObj.getString(name));
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
                log.error("【进钱-收款】 系统异常!");
            }
        }else {
            wf.log("【进钱-收款】请求环境:测试环境", "调试");
            Map resultMap2 =  new HashMap<String, Object>();
            resultMap2.put("appId", "wx8632a91376b81e24");
            resultMap2.put("timeStamp", "1473130115327");
            resultMap2.put("status", "0");
            resultMap2.put("signType", "MD5");
            resultMap2.put("package", "prepay_id=wx20160906104835c93c892dc20513630129");
            resultMap2.put("callback_url", "");
            resultMap2.put("nonceStr", "1473130115327");
            resultMap2.put("paySign", "D5E9444409354CB0F8C90C6C866DDA4F");
            
            
            Map resultMap1 =  new HashMap<String, Object>();
            resultMap1.put("message", "成功");
            resultMap1.put("sign", "5AB79D21EA969ADED363ECEC705FDCA1");
          //  resultMap1.put("payInfo", resultMap2);
            resultMap1.put("customerNo", "8611116424");
            resultMap1.put("resultCode", "1625231433");
            resultMap1.put("payUrl", "https://pay.swiftpass.cn/pay/jspay?token_id=3f8a021cdf16590db471252a6e76c3e8&showwxtitle=1");
            resultMap1.put("code", "0");
            resultMap1.put("status", "0");
            resultMap1.put("appId", "wx8632a91376b81e24");
            resultMap1.put("timeStamp", "1473130115327");
            resultMap1.put("status", "0");
            resultMap1.put("signType", "MD5");
            resultMap1.put("package", "prepay_id=wx20160906104835c93c892dc20513630129");
            resultMap1.put("callback_url", "");
            resultMap1.put("nonceStr", "1473130115327");
            resultMap1.put("paySign", "D5E9444409354CB0F8C90C6C866DDA4F");
          
           // String info = "{\"message\":\"成功\",\"sign\":\"570F2211FF1C13BFECEE66A2D5220796\",\"payInfo\":\"{\"appId\":\"wx8632a91376b81e24\",\"timeStamp\":\"1473668719286\",\"status\":\"0\",\"signType\":\"MD5\",\"package\":\"prepay_id=wx20160912162519bc70ae17990352093168\",\"callback_url\":null,\"nonceStr\":\"1473668719286\",\"paySign\":\"C7366069E6BBC1CC790A635CB67A13AE\"}\",\"customerNo\":\"8611116424\",\"resultCode\":\"1625231433\",\"payUrl\":\"https://pay.swiftpass.cn/pay/jspay?token_id=3f8a021cdf16590db471252a6e76c3e8&showwxtitle=1\",\"code\":\"0\"}";
            //Map<String, String> resultDebugMap = JSONUtil.parseToBean(info);
            resultMap = resultMap1;
        }

        PurchaseResult pr = new PurchaseResult();
        pr.setReqMsg("获取交易订单失败,请稍后再试!");
        pr.setStatus(0);
        pr.setReqCode("0001");

        if(resultMap.isEmpty()){
            pr.setReqMsg("获取交易订单失败,请稍后再试!");
            return pr;
        }

        String code = resultMap.get("code");
        String status = resultMap.get("status");

        if(code.equals("0") && status.equals("0")){//通讯成功
            if(resultMap.containsKey("payUrl") && StringUtils.isNotBlank(resultMap.get("payUrl"))){
                pr.setPayUrl(resultMap.get("payUrl"));//返回的扫码支付地址
                pr.setAppId(resultMap.get("appId"));
                pr.setTimestamp(resultMap.get("timeStamp"));
                pr.setNonceStr(resultMap.get("nonceStr"));
                pr.setPrepayId(resultMap.get("package"));
                pr.setPaySign(resultMap.get("paySign"));
                pr.setResultCode(resultMap.get("resultCode"));
                pr.setCustomerNo(customer_no);
                pr.setReqMsg("获取交易订单成功!");
                pr.setReqCode("0000");
            }else {
                pr.setReqMsg("获取交易订单失败,请稍后再试!");
            }
        }else {
            String message = resultMap.get("message");
            pr.setReqMsg(message);
        }
        return pr;
    }

    /**
     * 冲正
     * @param out_trade_no 商户系统内部订单号
     * @return
     * @throws Exception
     */
    public RevocationResult revocation(String out_trade_no)throws Exception {

        String reqUrl = "https://pay.swiftpass.cn/pay/gateway";
        String service = "unified.micropay.reverse";

        log.info("【进钱-冲正 请求参数】out_trade_no: " + out_trade_no);
        wf.log("【进钱-冲正 请求参数】out_trade_no: " + out_trade_no, "调试");

        String nonceStr = DesUtil.generate32Key();

        SortedMap<String,String> map = new TreeMap<>();
        map.put("service", service);
        map.put("version", version);
        map.put("sign_type", signType);
        map.put("mch_id", customer_no);
        map.put("nonce_str", nonceStr);
        map.put("out_trade_no",out_trade_no);

        Map<String,String> params = SignUtils.paraFilter(map);
        StringBuilder buf = new StringBuilder((params.size() +1) * 10);
        SignUtils.buildPayParams(buf,params,false);
        String preStr = buf.toString();
        String sign = MD5.sign(preStr, "&key=" + MD5Key, "utf-8");

        map.put("sign",sign);

        log.info("【进钱-冲正 请求参数】:" + XmlUtils.parseXML(map));

        Map<String, String> resultMap = new HashedMap();
        if(ConConfig.isFormal()){
            CloseableHttpResponse response = null;
            CloseableHttpClient client = null;
            try {
                HttpPost httpPost = new HttpPost(reqUrl);
                StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8");
                httpPost.setEntity(entityParams);
                httpPost.setHeader("Content-Type", "text/xml;charset=ISO-8859-1");
                client = HttpClients.createDefault();
                response = client.execute(httpPost);
                if (response != null && response.getEntity() != null) {
                    resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
                }
            }catch (Exception e){
                e.printStackTrace();
                log.error("【进钱-冲正】 系统异常!");
            }
        }else {
            //TODO:补充范例
            resultMap = null;
        }

        log.info("【进钱-冲正 响应参数】:" + XmlUtils.toXml(resultMap));

        RevocationResult rr = new RevocationResult();
        rr.setReqCode("0001");
        rr.setReqMsg("交易撤消失败!");
        rr.setStatus(0);

        if(resultMap.isEmpty()){
            rr.setReqMsg("操作失败,系统未响应!");
            return rr;
        }

        //校验签名
        if(resultMap.containsKey("sign")){
            if(!SignUtils.checkParam(resultMap, MD5Key)) {
                rr.setReqMsg("验证签名不通过!");
                return rr;
            }
        }

        String status = resultMap.get("status");
        String message = resultMap.get("message");

        if(StringUtils.isNotBlank(message)){
            rr.setReqMsg(message);
            return rr;
        }

        if(status.equals("0")){
            String result_code  = resultMap.get("result_code");
            if(result_code.equals("0")){
                rr.setReqCode("0000");
                rr.setReqMsg("交易撤消成功!");
                rr.setStatus(1);
            }
        }else {
            String err_code = resultMap.get("err_code");
            rr.setReqMsg(err_code);
        }
        return rr;
    }


    /**
     * 查询交易订单
     * @param out_trade_no 商户系统内部订单号
     * @return RevocationResult
     * @throws Exception
     */
    public RevocationResult queryorder(String out_trade_no)throws Exception {

        String reqUrl = "url:https://pay.swiftpass.cn/pay/gateway";
        String service = "unified.trade.query";

        log.info("【进钱-查询 请求参数】out_trade_no: " + out_trade_no);
        wf.log("【进钱-查询 请求参数】out_trade_no: " + out_trade_no, "调试");

        String nonceStr = DesUtil.generate32Key();

        SortedMap<String,String> map = new TreeMap<>();
        map.put("service", service);
        map.put("version", version);
        map.put("sign_type", signType);
        map.put("mch_id", customer_no);
        map.put("nonce_str", nonceStr);
        map.put("out_trade_no",out_trade_no);

        Map<String,String> params = SignUtils.paraFilter(map);
        StringBuilder buf = new StringBuilder((params.size() +1) * 10);
        SignUtils.buildPayParams(buf,params,false);
        String preStr = buf.toString();
        String sign = MD5.sign(preStr, "&key=" + MD5Key, "utf-8");

        map.put("sign",sign);
        log.info("【进钱-查询 请求参数】:" + XmlUtils.parseXML(map));

        Map<String, String> resultMap = new HashedMap();

        if(ConConfig.isFormal()){
            CloseableHttpResponse response = null;
            CloseableHttpClient client = null;
            try {
                HttpPost httpPost = new HttpPost(reqUrl);
                StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8");
                httpPost.setEntity(entityParams);
                httpPost.setHeader("Content-Type", "text/xml;charset=ISO-8859-1");
                client = HttpClients.createDefault();
                response = client.execute(httpPost);
                if (response != null && response.getEntity() != null) {
                    resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
                }
            }catch (Exception e){
                e.printStackTrace();
                log.error("进钱-订单查询】 请求时系统异常!");
            }
        }else {
            resultMap = null;
        }

        log.info("【进钱-查询 响应参数】:" + XmlUtils.toXml(resultMap));

        RevocationResult rr = new RevocationResult();
        rr.setReqCode("0001");
        rr.setReqMsg("查询交易订单失败!");
        rr.setStatus(0);

        if(resultMap.isEmpty()){
            rr.setReqMsg("操作失败,系统未响应!");
            return rr;
        }

        //校验签名
        if(resultMap.containsKey("sign")){
            if(!SignUtils.checkParam(resultMap, MD5Key)) {
                rr.setReqMsg("验证签名不通过!");
                return rr;
            }
        }

        String status = resultMap.get("status");
        String message = resultMap.get("message");

        if(status.equals("0")){
            String result_code = resultMap.get("result_code");
            if(result_code.equals("0")){
                String trade_state = resultMap.get("trade_states");
                if(trade_state.equals("SUCCESS")){
                    rr.setReqCode("0000");
                    rr.setReqMsg("交易成功!");
                    rr.setStatus(1);
                }else if(trade_state.equals("NOTPAY")){
                    rr.setReqCode("0002");
                    rr.setReqMsg("交易失败,请确认是否输入支付密码 !");
                    rr.setStatus(0);
                }else if(trade_state.equals("CLOSED")){
                    rr.setReqCode("0003");
                    rr.setReqMsg("交易已关闭 !");
                    rr.setStatus(0);
                }else if(trade_state.equals("REVOKED") || trade_state.equals("REFUND")){
                    rr.setReqCode("0004");
                    rr.setReqMsg("交易已撤销 !");
                    rr.setStatus(0);
                }else if(trade_state.equals("PAYERROR")){
                    rr.setReqCode("0001");
                    rr.setReqMsg("交易失败 !");
                    rr.setStatus(0);
                }else if(trade_state.equals("USERPAYING")){
                    rr.setReqCode("0005");
                    rr.setReqMsg("用户交易中!");
                    rr.setStatus(0);
                }
            }else {
                String err_msg = resultMap.get("err_msg");
                String err_code = resultMap.get("err_code");
                rr.setReqMsg(err_msg);
                rr.setReqCode(err_code);
            }
        }else {
            rr.setReqMsg(message);
        }
        return rr;
    }
}
